#include "PlayerManager.h"
#include "EnemyManager.h"
#include "GameMath.h"
#include "../data/GameInfo.h"
#include "../data/Creator.h"

PlayerManager::PlayerManager()
{
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_SLIME));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_WOLF));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_HONEYBEE));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_BOAR));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_GUARD));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_WOLFHIME));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_SWORDMAN));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_ARCHER));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_MAGICIAN));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_SUCCUBUS));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_SATAN));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_PHYSICIAN));
    AddPlayer(Creator::CreateHero(CharacterId::CHARACTER_DEVIL));
}

void PlayerManager::OnUpdate(double delta)
{
    auto &players = GameInfo::Instance().players;
    if (idx >= players.size()) {
        ChangerPlayer();
    }
    std::shared_ptr<Character> player = GetPlayer();
    player->direction = GameVector(player->isMoving[Facing::Right] - player->isMoving[Facing::Left],
                                   player->isMoving[Facing::Down] - player->isMoving[Facing::Up]);
    player->OnUpdate(delta);
}

void PlayerManager::OnRender()
{
    GetPlayer()->OnRender();
}

void PlayerManager::KeyDown(int32_t &code)
{
    switch (code) {
        case SDLK_a:
            GetPlayer()->isMoving[Facing::Left] = true;
            break;
        case SDLK_d:
            GetPlayer()->isMoving[Facing::Right] = true;
            break;
        case SDLK_w:
            GetPlayer()->isMoving[Facing::Up] = true;
            break;
        case SDLK_s:
            GetPlayer()->isMoving[Facing::Down] = true;
            break;
        case SDLK_j:
            KeyOnJ();
            break;
        case SDLK_k:
            ReleaseSkill(1);
            break;
        case SDLK_l:
            break;
        case SDLK_u:
            ReleaseSkill(2);
            break;
        case SDLK_i:
            ReleaseSkill(3);
            break;
        case SDLK_o:
            ReleaseSkill(4);
            break;
        case SDLK_f:
            GetPlayer()->Die();
            break;
        case SDLK_t:
            ChangerPlayer();
            break;
        default:
            break;
    }
}

void PlayerManager::KeyUp(int32_t &code)
{
    switch (code) {
        case SDLK_a:
            GetPlayer()->isMoving[Facing::Left] = false;
            break;
        case SDLK_d:
            GetPlayer()->isMoving[Facing::Right] = false;
            break;
        case SDLK_w:
            GetPlayer()->isMoving[Facing::Up] = false;
            break;
        case SDLK_s:
            GetPlayer()->isMoving[Facing::Down] = false;
            break;
        default:
            break;
    }
}

GameVector PlayerManager::GetPosition()
{
    return GetPlayer()->position;
}

std::shared_ptr<Character> PlayerManager::GetPlayer()
{
    return GameInfo::Instance().players[idx];
}

void PlayerManager::AddPlayer(const std::shared_ptr<Character> &player)
{
    player->id = 0;
    player->hp = player->maxHp = 1000;
    for (int i = Facing::Down; i < Facing::SIZE; i++) {
        player->animAttack[i].onFinished = [player] { player->OnAttack(GameInfo::Instance().enemies); };
        player->animRigidity[i].timer.waitTime = 0.01;
        player->animDie[i].onFinished = [] {
            GAME_INFO.isGameOver = true;
            GAME_MUSIC.Play(GAME_INFO.musicPool[MusicId::MUSIC_HEISHENHUAPI]);
        };
    }
    GameInfo::Instance().players.emplace_back(player);
}

void PlayerManager::ChangerPlayer()
{
    auto &players = GameInfo::Instance().players;
    auto tempPlayer = players[idx];
    idx++;
    idx %= (int) players.size();
    players[idx]->position = tempPlayer->position;
    players[idx]->hp = tempPlayer->hp;
    players[idx]->mp = tempPlayer->mp;
    memcpy(players[idx]->isMoving, tempPlayer->isMoving, sizeof(players[idx]->isMoving));
    players[idx]->facing = tempPlayer->facing;
}

void PlayerManager::ReleaseSkill(int skillId)
{
    GetPlayer()->ReleaseSkill(skillId);
}

void PlayerManager::KeyOnJ()
{
    auto player = GAME_INFO.players[idx];
    if (player->isMoving[player->facing]) {
        ReleaseSkill(0);
        return;
    }
    player->Attack();
}

